﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Hsenl {
    /*
     * 可以在需要遍历内部数组的时候采用. 例如class1中有个private list<xxx> 字段, 如果我们想让外部可以遍历他, 大概有以下几种方法
     * 返回他的IReadOnlyList、返回他的IEnumerable<xxx>、通过Foreach(Action<xxx> callback)、返回一个新的数组xxx[]
     * 第一种, 不方便, 且返回了源指针
     * 第二种, 虽然写起来方便, 但会产生gc
     * 第三种, 写起来方便, 且如果有递归需求也很好实现. 但要避免外部引用, 否则会产生gc, 要避免gc的话, 还需要特别处理, 麻烦
     * 第四种, 效率低, 且产生GC
     * 现在, 还可以使用这种方式, 快速的实现foreach的功能, 保持私密的同时, 安全, 快速, 0gc.
     */

    public readonly struct IteratorList<T> : IEnumerable<T> {
        private readonly bool _noNull;
        private readonly List<T>.Enumerator _enumerator;

        public IteratorList(List<T> list) {
            if (list == null)
                throw new ArgumentNullException(nameof(list));

            this._noNull = true;
            this._enumerator = list.GetEnumerator();
        }

        public Enumerator GetEnumerator() => this._noNull ? new Enumerator(this._enumerator) : default;
        IEnumerator<T> IEnumerable<T>.GetEnumerator() => this.GetEnumerator();
        IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator();

        public struct Enumerator : IEnumerator<T> {
            private readonly bool _noNoll;
            private List<T>.Enumerator _enumerator;

            public T Current { get; private set; }

            object IEnumerator.Current => this.Current;

            public Enumerator(List<T>.Enumerator enumerator) {
                this._noNoll = true;
                this._enumerator = enumerator;
                this.Current = default;
            }

            public bool MoveNext() {
                if (!this._noNoll)
                    return false;

                var next = this._enumerator.MoveNext();
                this.Current = this._enumerator.Current;
                return next;
            }

            public void Reset() { }


            public void Dispose() {
                this.Reset();
            }
        }
    }
}